<?php /* Copyright 2010 Karl R. Wilcox

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

function setpGlobals() {
  global $p_globals;
  
  $p_globals = array (
    'offield' => null,
    'offirst' => null,
    'ofsecond' => null,
    'ofthird' => null,
    'offourth' => null,
    'ofsame' => null,
    'oflast' => null,
    'asmany' => null,
  );
}

function parser_message($category, $string, $file = '', $line = '' ) {
  global $dom, $parser_messages;

  $message = $dom->createElement('message');
  $message->setAttribute( 'tokens',tokens());
  $message->setAttribute( 'category',$category);
  if ( $file ) $message->setAttribute('filename', $file);
  if ( $line ) $message->setAttribute('line', $line);
  $text = $dom->createTextNode($string);
  $message->appendChild($text);
  $parser_messages->appendChild($message);
}

function deep_copy($node) {
  global $dom;

  $newnode = $dom->createElement($node->nodeName);
  foreach ($node->attributes as $attribute) {
    $newnode->setAttribute($attribute->name,$attribute->value);
  }
  foreach ($node->childNodes as $child) {
    $newnode->appendChild(deep_copy($child));
  }
  return $newnode;
}

function copy_children(&$fromNode, &$toNode) {
  $fromNode_childNodes = $fromNode->childNodes;
  $length = $fromNode_childNodes->length;
  $fromChildren_array = array();
 
  for($i = 0; $i < $length; $i++)
    $fromChildren_array[] = $fromNode_childNodes->item($i);
 
  foreach($fromChildren_array as $old_c)
     $toNode->appendChild($old_c);
}

function save() {
  global $cur_word;

  return $cur_word;
}

function restore($state) {
  global $cur_word;

  $cur_word = $state;
}

function next_word() { // return next token (or null)
  global $cur_word, $words;

  if ( $cur_word > count($words) ) return null;
  return $words[$cur_word++];
}

function get_tokens($num = 1) {
  global $cur_word, $words;

  if ( $num < 0 ) $num = 1;

  $retval = '';
  for ( $i = 0; $i < $num; $i++ )
    if ( ($token = next_word()) != null ) $retval .= $token . ' ';
  return (rtrim($retval));
}

function lookahead($inc = 1) {
  global $cur_word, $words;

  if ((($cur_word + $inc) > count($words)) or (($cur_word + $inc) < 0)) {
    return false;
  } else {
    $cur_word += $inc;
    return true;
  }
}

function andd() {
  $and_words = array (
    array ( true, '(and|&|also)' ),
    array ( true, '(and|&) also' ),
  );

  if ( search_match($and_words) ) return true;
  return false;
}

function semicolon($lookback = true) {
  $semi = array (
    array ( true, ';'),
    array ( true, '\\.'), // need to escape '.' as this is regex special character
   );
  $retval = false;
  if ( search_match($semi) != null ) 
    $retval = true;
  if ( $lookback ) {
    $state = save();
    if ( lookahead(-1) && search_match($semi) != null ) $retval = true;
    restore($state);
  }
  return $retval;
}

function comma() {
  // Consume a comma (or similar) character if present, and return true
  // But also return true if the *previous* character was a comma
  $commas = array (
    array ( true, ',' ),
  );

  if ( search_match($commas) != null ) return true;
  $state = save();
  if ( lookahead(-1) && search_match($commas) != null ) return true;
  restore($state);
  return false;
}

function tokens() {
  global $matched_tokens;

  $retval = $matched_tokens;
  $matched_tokens = '';
  return $retval;
}

function unique($prefix = 'item') {
  static $uni_num = 0;

  $uni_num += 1;
  return "$prefix$uni_num";
}

function make_mod($name, $param = null, $tokens = null ) {
  global $dom;

  $mod = $dom->createElement('modifier');
  $mod->setAttribute('name', $name);
  if ( $param ) $mod->setAttribute('param', $param);
  if ( $tokens ) $mod->setAttribute('tokens', $tokens);
  $mod->setAttribute('tokens',tokens());
  return $mod;
}

function make_colour($colour, $index='1') {
  global $dom;

  $tinc = $dom->createElement('tincture');
  $col = $dom->createElement('colour');
  $col->setAttribute('name',$colour);
  $tinc->setAttribute('index',$index);
  $tinc->appendChild($col);
  return $tinc;
}

function get_mod($node, $name) {
// FIX sometimes we seem to call this with a DOMNodeList (from error_log on 18/7/14)
  if ( $node != null and get_class($node) <> 'DOMNodeList' and $node->hasChildNodes()) {
    foreach ( $node->childNodes as $child ) {
      if ( $child->nodeName == 'modifier' and $child->getAttribute('name') == $name ) {
        $retval = $child->getAttribute('param');
        if ( $retval == null ) $retval = true; // Just say the modifier exists
        return $retval;
      }
    }
  }
  return null;
}

function has_feature($node, $name) {
  if ( $node == null or !$node->hasChildNodes()) return null;
  foreach ( $node->childNodes as $child ) {
    if ( $child->nodeName == 'feature' and $child->getAttribute('name') == $name ) {
      return true;
    }
  }
  return false;
}

function get_mods($node, $name) {
  $retval = array();
  if ( $node == null ) return null;
  foreach ( $node->childNodes as $child ) {
    if ( $child->nodeName == 'modifier' and $child->getAttribute('name') == $name ) {
      $val = $child->getAttribute('param');
      if ( $val == null ) $val = true; // Just say the modifier exists
      $retval[] = $val;
    }
  }
  return $retval;
}


function get_mod_node($node, $name) {
  if ( $node == null ) return null;
  foreach ( $node->childNodes as $child ) {
    if ( $child->nodeName == 'modifier' and $child->getAttribute('name') == $name ) {
      return $child;
    }
  }
  return null;
}


function get_child($node,$nodeName) {
  $retval = null;
  foreach ( $node->childNodes as $child ) {
    if ( $child->nodeName == $nodeName ) {
      $retval = $child;
      break;
    }
  }
  return $retval;
}

function get_rgb($tinc_node) {
	$col = $tinc_node->firstChild;
	if ( !$col or $col->nodeName != 'colour' ) {
	  draw_message('warning','plain colour expected');
	  return ( '#555555' );
	} // So now we have a colour node
	return rgb($col->getAttribute('name'));
}

function get_tincture($node,$index=null) {
  foreach ( $node->childNodes as $child ) {
    if ( $child->nodeName == 'tincture' ) {
		  if ( !$index ) return $child;
			if ( $child->getAttribute('index') == $index ) {
			  return $child;
			}
    }
  }
  return null; // TODO should this return missing node?
}

